05. StatisticsViewModelTest
In the next step, you'll be writing tests for the StatisticViewModel. As a reminder, the StatisticViewModel holds all the data and does all of the calculations for the Statistics Screen:
To set things up for testing the StatisticViewModel, you'll need to make two code changes:
- Update
StatisticViewModelso that you can inject the fake repository. This is a review of what you did in 5.2 Testing: Intro to Test Doubles when you used the fake repository. - Do the standard test setup for
StatisticViewModelTest.
Both of these are review and unrelated to coroutine timing, so feel free to copy/paste.
Step 1: Update StatisticsViewModel for Dependency Injection
- Open
StatisticsViewModel. - Change the constructor of
StatisticsViewModelto take inTasksRepositoryinstead of constructing it inside the class, so that you can inject a fake repository for testing:
StatisticsViewModel.kt
// REPLACE
class StatisticsViewModel(application: Application) : AndroidViewModel(application) {
private val tasksRepository = (application as TodoApplication).taskRepository
// Rest of class
}
// WITH
class StatisticsViewModel(
private val tasksRepository: TasksRepository
) : ViewModel() {
// Rest of class
}
- At the bottom of the
StatisticsViewModelfile, outside the class, add aTasksViewModelFactorywhich takes in a plainTasksRepository:
StatisticsViewModel.kt
@Suppress("UNCHECKED_CAST")
class StatisticsViewModelFactory (
private val tasksRepository: TasksRepository
) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>) =
(StatisticsViewModel(tasksRepository) as T)
}
- Update
StatisticsFragmentto use the factory.
StatisticsFragment.kt
// REPLACE
private val viewModel by viewModels<TasksViewModel>()
// WITH
private val viewModel by viewModels<StatisticsViewModel> {
StatisticsViewModelFactory(
(requireContext().applicationContext as TodoApplication).taskRepository
)
}
- Run your application code and navigate to the StatisticsFragment to make sure your statistics screen works just like before.
Step 2: Create StatisticsViewModelTest
- Open
StatisticsViewModel.kt. - Right-click on the
StatisticsViewModelclass name and select Generate, then Test. - Follow the prompts to create
StatisticsViewModelTestin the test source set.
Follow the steps below to set up your StatisticsViewModel test as you've done previously. This is a good review of what goes into a view model test:
- Add the
InstantTaskExecutorRulesince you are testing Architecture Components. - Add the
MainCoroutineRulesince you are testing coroutines and view models. - Create fields for the subject under test (
StatisticsViewModel) and test doubles for its dependencies (FakeTestRepository). - Create a
@Beforemethod that sets up the subject under test and dependencies.
Your test should look like this:
StatisticsViewModelTest.kt
@ExperimentalCoroutinesApi
class StatisticsViewModelTest {
// Executes each task synchronously using Architecture Components.
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
// Set the main coroutines dispatcher for unit testing.
@ExperimentalCoroutinesApi
@get:Rule
var mainCoroutineRule = MainCoroutineRule()
// Subject under test
private lateinit var statisticsViewModel: StatisticsViewModel
// Use a fake repository to be injected into the view model.
private lateinit var tasksRepository: FakeTestRepository
@Before
fun setupStatisticsViewModel() {
// Initialise the repository with no tasks.
tasksRepository = FakeTestRepository()
statisticsViewModel = StatisticsViewModel(tasksRepository)
}
}